package com.example.base.adapter.selector

import android.util.SparseBooleanArray
import java.util.ArrayList

class Selector @JvmOverloads constructor(private var mSelectMode: Int = SINGLE_MODE) {
    private val mSelections = SparseBooleanArray()
    private val mTracker = WeakHolderTracker()
    private var mIsSelectable = true
    var isSelectable: Boolean
        get() = mIsSelectable
        set(isSelectable) {
            mIsSelectable = isSelectable
            refreshAllHolders()
        }

    private fun refreshAllHolders() {
        for (holder in mTracker.trackedHolders) {
            refreshHolder(holder)
        }
    }

    var selectMode: Int
        get() = mSelectMode
        set(mode) {
            if (mSelectMode != mode) {
                mSelectMode = mode
                clearSelections()
            }
        }

    private fun refreshHolder(holder: ISelectableHolder?) {
        if (holder == null) {
            return
        }
        holder.setSelectable(mIsSelectable)
        val isActivated = mSelections[holder.getPosition()]
        holder.setActivated(isActivated)
    }

    fun isSelected(position: Int): Boolean {
        return mSelections[position]
    }

    fun setSelected(position: Int, selected: Boolean) {
        if (mIsSelectable) {
            when (mSelectMode) {
                SINGLE_MODE -> {
                    if (selected) {
                        for (selectedPosition in selectedPositions) {
                            if (selectedPosition != position) {
                                mSelections.put(selectedPosition, false)
                                refreshHolder(mTracker.getHolder(selectedPosition))
                            }
                        }
                    }
                    mSelections.put(position, !mSelections[position])
                    refreshHolder(mTracker.getHolder(position))
                }
                MULTI_MODE -> {
                    mSelections.put(position, selected)
                    refreshHolder(mTracker.getHolder(position))
                }
                SINGLE_UNCANCELL_MODE -> {
                    if (selected) {
                        for (selectedPosition in selectedPositions) {
                            if (selectedPosition != position) {
                                mSelections.put(selectedPosition, false)
                                refreshHolder(mTracker.getHolder(selectedPosition))
                            }
                        }
                    }
                    mSelections.put(position, true)
                    refreshHolder(mTracker.getHolder(position))
                }
            }
        }
    }

    fun clearSelections() {
        mSelections.clear()
        refreshAllHolders()
    }

    fun removed(key: Int) {
        mSelections.delete(key)
        refreshAllHolders()
    }

    val selectedPositions: List<Int>
        get() {
            val positions: MutableList<Int> = ArrayList()
            for (i in 0 until mSelections.size()) {
                if (mSelections.valueAt(i)) {
                    positions.add(mSelections.keyAt(i))
                }
            }
            return positions
        }

    val selectedCount: Int
        get() = selectedPositions.size

    val singleSelectedPosition: Int
        get() {
            val positions = selectedPositions
            return if (positions.size < 1) -1 else positions[0]
        }

    fun bindHolder(holder: ISelectableHolder?, position: Int) {
        mTracker.bindHolder(holder, position)
        refreshHolder(holder)
    }

    fun setSelected(holder: ISelectableHolder, isSelected: Boolean) {
        setSelected(holder.getPosition(), isSelected)
    }

    fun toggle(position: Int) {
        val isSelected = isSelected(position)
        setSelected(position, !isSelected)
    }

    fun tapSelection(holder: ISelectableHolder): Boolean {
        return tapSelection(holder.getPosition())
    }

    private fun tapSelection(position: Int): Boolean {
        return if (mIsSelectable) {
            val isSelected = isSelected(position)
            setSelected(position, !isSelected)
            true
        } else {
            false
        }
    }

    companion object {
        // public static final int NO_SELECT_MODE = 0;
        const val UNSELECT_MODE = 0
        const val SINGLE_MODE = 1
        const val MULTI_MODE = 2
        const val SINGLE_UNCANCELL_MODE = 3
    }

}